#include "SudokuSolver.h"

SudokuSolver::SudokuSolver(TeamType T, SudokuType S) : m_nS(S), m_nT(T)
{
	IntialTeam();
}

SudokuSolver::~SudokuSolver(void)
{
	delete []m_pExtraTeam;
}

GridTeam* SudokuSolver::GetTeam(int index)
{
	int t_nType = index / g_cnTeamSize;
	int t_nIndex = index % g_cnTeamSize;

	switch (t_nType)
	{
	case 0:
		return &(m_RowTeam[t_nIndex]);

	case 1:
		return &(m_ColTeam[t_nIndex]);

	case 2:
		return &(m_BlockTeam[t_nIndex]);

	case 3:
		if ( m_nS != COLOR )
		{
			return m_pExtraTeam;
		} 
		else
		{
			return &(m_pExtraTeam[t_nIndex]);
		}

	default:
		cout << "invalid team index " << index << endl;
		exit(0);;
	}

	return NULL;
}

SudokuSolver::SudokuSolver(TeamType T, SudokuType S, const char* filename) : m_nS(S), m_nT(T)
{
	ifstream inf(filename, ios::in);
	if ( !inf )
	{
		cout << filename << " does not exist." << endl;
		exit(0);
	}

	IntialTeam();
	int t_nStatus = TextAnalyzer(inf);
	if ( t_nStatus < 0 )
	{
		cout << "Text analyze failed" << endl;
		exit(0);
	}

	inf.close();
}

int SudokuSolver::SolveStep(void)
{
	int i;
	for ( i = 0; i < m_nTeamSize; ++i )
	{
		GetTeam(i)->CalcCount();
	}

	int t_nStatus;
	t_nStatus = TrySingle();

	return 0;
}

int SudokuSolver::TrySingle(void)
{
	int i;
	SingleGrid *t_pFind = NULL;
	for ( i = 0; i < m_nTeamSize; ++i )
	{
		t_pFind = GetTeam(i)->TrySingle();
		if ( t_pFind != NULL )
		{
			break;
		}
	}

	if ( i == m_nTeamSize )
	{
		return 0;
	}

	int t_nDigit = t_pFind->m_nDigit;
	return 1;
}

int SudokuSolver::IntialTeam(void)
{
	m_nTeamSize = 3 * g_cnTeamSize;

	int i, j;
	for ( i = 0; i < g_cnTeamSize; ++i )
	{
		g_pData[i] = m_Grid[i];
		for ( j = 0; j < g_cnTeamSize; ++j )
		{
			m_Grid[i][j].SetCoord(i, j);
			m_Grid[i][j].m_pOwner = this;
		}
	}

	for ( i = 0; i < g_cnTeamSize; ++i )
	{
		m_RowTeam[i].m_nTeamIndex = i;
		m_RowTeam[i].SetAsRow(i);
		m_ColTeam[i].m_nTeamIndex = g_cnTeamSize + i;
		m_ColTeam[i].SetAsCol(i);
		m_BlockTeam[i].m_nTeamIndex = 2 * g_cnTeamSize + i;
	}

	if ( m_nT == STRAIGHT )
	{
		for ( i = 0; i < g_cnTeamSize; ++i )
		{
			m_BlockTeam[i].SetNormalBlock(i);
		}
	}

	switch (m_nS)
	{
	case NORMAL:
		m_pExtraTeam = NULL;
		break;

	case HYPER:
		++m_nTeamSize;
		break;

	case PERCENT:
		++m_nTeamSize;
		break;

	case COLOR:
		m_nTeamSize += g_cnTeamSize;

		m_pExtraTeam = new GridTeam[g_cnTeamSize];
		for ( i = 0; i < g_cnTeamSize; ++i )
		{
			m_pExtraTeam[i].SetAsColor(i);
		}
		break;

	default:
		cout << "invalid SudokuType" << endl;
		exit(0);
	}
	return 0;
}

ostream &operator<< (ostream &os, const SudokuSolver &ss)
{
	int i;
	os << "Row:" << endl;
	for ( i = 0; i < g_cnTeamSize; ++i )
	{
		os << ss.m_RowTeam[i];
	}

	os << endl << "Col:" << endl;
	for ( i = 0; i < g_cnTeamSize; ++i )
	{
		os << ss.m_ColTeam[i];
	}

	os << endl << "Block:" << endl;
	for ( i = 0; i < g_cnTeamSize; ++i )
	{
		os << ss.m_BlockTeam[i];
	}

	switch (ss.m_nS)
	{
	case NORMAL:
		break;

	case HYPER:
		break;

	case PERCENT:
		break;

	case COLOR:
		os << endl << "Color" << endl;
		for ( i = 0; i < g_cnTeamSize; ++i )
		{
			os << ss.m_pExtraTeam[i];
		}
		break;

	default:
		cout << "invalid SudokuType" << endl;
		exit(0);
	}
	return os;
}


SudokuSolver::SudokuSolver(const char* filename)
{
	ifstream inf(filename, ios::in);
	if ( !inf )
	{
		cout << filename << " does not exist." << endl;
		exit(0);
	}

	int t_nS;
	int t_nT;
	inf >> t_nS >> t_nT;

	m_nS = (enum SudokuType)t_nS;
	m_nT = (enum TeamType)t_nT;

	IntialTeam();

	int t_nStatus = TextAnalyzer(inf);
	if ( t_nStatus < 0 )
	{
		cout << "Text analyze failed" << endl;
		exit(0);
	}

	inf.close();
}

int SudokuSolver::TextAnalyzer(ifstream& inf)
{
	return 0;
}
